package com.bestcem.xm.txtanls.grpc.client;

import com.bestcem.xm.bi.grpc.v1.services.*;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.txtanls.service.dto.train.ClickHouseDTO;
import com.bestcem.xm.txtanls.service.dto.train.ClickhouseColumnDTO;
import com.bestcem.xm.txtanls.service.impl.AsyncTaskServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import zhongyan.xm.base.v1.Base;

import java.util.*;

import static com.bestcem.xm.common.core.constant.Constants.LIMIT;

/**
 * 倍市得 clickhouse 模块相关rpc接口客户端
 *
 * @author gy.liu
 * @version 1.0
 * @date 2021/6/10 13:34
 **/
@Slf4j
@Service
public class ClickhouseGrpcService {

    @GrpcClient(GrpcClientNames.XM)
    private BiServiceGrpc.BiServiceBlockingStub biServiceBlockingStub;

    /**
     * 调用clickhouse接口
     *
     * @param workTableId             workTableId
     * @param clickhouseColumnDTOList 要查询的列信息
     * @param skip                    查询数据的偏移量
     * @return ClickHouseDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/22 17:00
     */
    public ClickHouseDTO queryClickHouse(String workTableId, Integer skip,
                                         List<ClickhouseColumnDTO> clickhouseColumnDTOList, List<Filter> filterList) {
        // 要查询的列
        List<NewColumn> columns = new ArrayList<>();
        if (!CollectionUtils.isEmpty(clickhouseColumnDTOList)) {
            for (ClickhouseColumnDTO clickhouseColumnDTO : clickhouseColumnDTOList) {
                NewColumn column = NewColumn.newBuilder()
                        .setCol(clickhouseColumnDTO.getCol())
                        .setColumnId(clickhouseColumnDTO.getColumnId())
                        .setName(clickhouseColumnDTO.getName())
                        .setDataType(clickhouseColumnDTO.getDataType())
                        .setDateType(clickhouseColumnDTO.getDateType())
                        .build();
                columns.add(column);
            }
        }
        SearchRequest search = SearchRequest.newBuilder()
                .setWorktableId(workTableId)
                .addAllNewColumns(columns)
                .setLimit(LIMIT)
                .setSkip(skip)
                .addAllFilters(filterList)
                .addAllPivots(new ArrayList<>())
                .build();
        if (log.isWarnEnabled()) {
            log.warn("[Txtanls] ClickhouseGrpcService.queryClickHouse 入参: {}", search);
        }
        SearchResponse searchResponse = biServiceBlockingStub.getRawData(search);
        if (Objects.isNull(searchResponse)) {
            log.error("[Txtanls] {} ClickhouseGrpcService.queryClickHouse 接口返回空", workTableId);
        }
        if (log.isWarnEnabled()) {
            log.warn("[Txtanls] ClickhouseGrpcService.queryClickHouse 返回: {}", searchResponse);
        }
        return responseToClickhouseDTO(searchResponse, skip);
    }


    /**
     * 查询问卷对应的 worktableId
     *
     * @param surveyId 问卷id
     * @return String
     * @author gy.liu
     * @date 2021/6/22 13:44
     */
    public String getSurveyWorkTableId(String surveyId) {
        GetProjectWorktableRequest project = GetProjectWorktableRequest.newBuilder().setProjectId(surveyId).build();
        if (log.isWarnEnabled()) {
            log.warn("[Txtanls] ClickhouseGrpcService.getSurveyWorkTableId 入参: {}", project);
        }
        GetProjectWorktableResponse response = biServiceBlockingStub.getProjectWorktable(project);
        if (log.isWarnEnabled()) {
            log.warn("[Txtanls] ClickhouseGrpcService.getSurveyWorkTableId 返回: {}", response);
        }
        if (Base.Code.ERROR.equals(response.getStatus().getCode())) {
            log.error("[Txtanls] 获取问卷项目WorktableId失败: {}", surveyId);
            return null;
        }
        return response.getId();
    }

    /**
     * 获取 worktable 下所有数据的条数
     *
     * @param workTableId                  worktableId
     * @param worktableDataTotalColumnList worktable里所有的列信息
     * @return Worktable data count
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/28 11:46
     */
    public long getWorktableDataTotal(String workTableId, List<ClickhouseColumnDTO> worktableDataTotalColumnList) {
        List<NewColumn> columns = new ArrayList<>();
        if (!CollectionUtils.isEmpty(worktableDataTotalColumnList)) {
            // 传所有字段; 如果只传某些字段, 而传的字段没数据的话, 会返回0, 而不是数据表长度
            for (ClickhouseColumnDTO columnDTO : worktableDataTotalColumnList) {
                NewColumn column = NewColumn.newBuilder()
                        .setCol(columnDTO.getCol())
                        .setColumnId(columnDTO.getColumnId())
                        .setName(columnDTO.getName())
                        .setDataType(columnDTO.getDataType())
                        .setDateType(columnDTO.getDateType())
                        .build();
                columns.add(column);
            }
        }
        SearchRequest request = SearchRequest.newBuilder()
                .setWorktableId(workTableId)
                .addAllNewColumns(columns)
                .setLimit(1)
                .setSkip(0)
                .addAllFilters(new ArrayList<>())
                .addAllPivots(new ArrayList<>())
                .build();
        if (log.isWarnEnabled()) {
            log.warn("[Txtanls] ClickhouseGrpcService.getWorktableDataTotal 入参: {}", request);
        }
        SearchResponse searchResponse = biServiceBlockingStub.getRawData(request);
        if (log.isWarnEnabled()) {
            log.warn("[Txtanls] ClickhouseGrpcService.getWorktableDataTotal 返回: {}", searchResponse);
        }
        return searchResponse.getTotal();
    }

    // ========================== private model convert ==========================


    /**
     * clickhouse返回数据转换为DTO
     *
     * @param response clickhouse 接口返回数据
     * @param skip     查询数据的偏移量
     * @return ClickHouseDTO
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/6/22 16:57
     */
    private ClickHouseDTO responseToClickhouseDTO(SearchResponse response, Integer skip) {
        ClickHouseDTO clickHouseDTO = new ClickHouseDTO();
        clickHouseDTO.setSkip(skip);
        clickHouseDTO.setTotal(response.getTotal());

        // 全部的列名
        List<String> colNameList = response.getHeadValue().getDataList();
        int len = colNameList.size();
        // 是否是问卷项目
        boolean isSurvey = colNameList.contains(AsyncTaskServiceImpl.COLLECTION_ID);
        // 全部的数据
        List<RowValue> columnValues = response.getBodyValuesList();

        // 填充所有的数据
        if (!CollectionUtils.isEmpty(columnValues)) {
            List<Map<String, String>> allRowsData = new ArrayList<>(columnValues.size());
            for (int index = 0; index < columnValues.size(); index++) {
                RowValue columnValue = columnValues.get(index);
                List<String> dataList = columnValue.getDataList();
                Map<String, String> rowData = new HashMap<>(len);
                // 存放数据的行号
                rowData.put(AsyncTaskServiceImpl.ROW_INDEX, columnValue.getName());
                for (int i = 0; i < len; i++) {
                    String temp = dataList.get(i);
                    if (ObjectUtils.isEmpty(temp)) {
                        temp = "";
                    }
                    rowData.put(colNameList.get(i), temp);
                }
                if (!isSurvey) {
                    rowData.put(AsyncTaskServiceImpl.COLLECTION_ID, String.valueOf(index));
                }
                allRowsData.add(rowData);
            }
            clickHouseDTO.setAllRowsData(allRowsData);
        }

        clickHouseDTO.setColNameList(colNameList);
        return clickHouseDTO;
    }
}
